#define GLEW_STATIC

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <cmath>
#include <Shader.h>
using namespace std;

// triangle points data       [x y z r g b]
float vertices[] =
{
   -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f,
   0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f,
   0.0f, 0.5f * sqrtf(3.0f) - 0.5f, 1.0f, 0.0f, 1.0f, 0.0f
};

float GenerateRandColor()
{
   return (rand() % 11 + 1) / 10;
}

int main()
{
   srand((unsigned int)time(NULL));

   // setting window config
   glfwInit();
   glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
   glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
   glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

   // create window
   GLFWwindow* window =
      glfwCreateWindow(800, 600, "Colorful Triangle", nullptr, nullptr);
   if (window == nullptr)
   {
      cout << "GLFW ERROR" << endl;
      glfwTerminate();
      return EXIT_FAILURE;
   }

   // binding window context
   glfwMakeContextCurrent(window);

   glewExperimental = true;

   // init glew
   if (glewInit() != GLEW_OK)
   {
      cout << "GLEW ERROR" << endl;
      glfwTerminate();
      return EXIT_FAILURE;
   }

   // set viewport
   glViewport(0, 0, 800, 600);

   // build shader
   Shader shader("shader.vert", "shader.frag");
   
   // build up pipeline
   unsigned int VAO;
   glGenVertexArrays(1, &VAO);
   glBindVertexArray(VAO);
   
   unsigned int VBO;
   glGenBuffers(1, &VBO);
   glBindBuffer(GL_ARRAY_BUFFER, VBO);

   glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

   // VAO vertex strategy
   glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
   glEnableVertexAttribArray(0);
   // VAO color strategy
   glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
   glEnableVertexAttribArray(1);

   // draw config
   glEnable(GL_CULL_FACE);
   glCullFace(GL_BACK);

   // rendering iteration
   while (glfwWindowShouldClose(window) == 0)
   {
      // set clear screen color
      glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
      glClear(GL_COLOR_BUFFER_BIT);

      // floating effect
      float timeValue = static_cast<float>(glfwGetTime());
      float colorValue = ::sin(timeValue) * 0.5f + 0.5f;
      vertices[4] = colorValue;
      vertices[9] = colorValue;
      vertices[17] = colorValue;

      // bind VAO VBO
      shader.Use();
      glBindVertexArray(VAO);
      glBindBuffer(GL_ARRAY_BUFFER, VBO);
      glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

      // render
      glDrawArrays(GL_TRIANGLES, 0, 3);
      glfwSwapBuffers(window);
      glfwPollEvents();  
   }

   glfwTerminate();

   return EXIT_SUCCESS;
}